package com.omega.framework.common.util;

import com.omega.framework.common.exception.BaseServiceException;
import com.xiaoleilu.hutool.collection.IterUtil;
import com.xiaoleilu.hutool.util.ArrayUtil;
import com.xiaoleilu.hutool.util.MapUtil;
import com.xiaoleilu.hutool.util.StrUtil;
import org.apache.commons.lang3.StringUtils;

import java.util.Date;
import java.util.Map;
import java.util.Objects;

/**
 * 断言工具类
 *
 * @author Lv.
 * @date 2022/11/2 16:09
 */
public class AssertUtil {

    /**
     * 断言对象是否为null ，如果为null抛出异常
     *
     * @param data                 被检查对象
     * @param baseServiceException 错误返回码
     * @param params               参数列表
     * @param <T>                  被检查对象泛型类型
     * @return 被检查后的对象
     */
    public static <T> T isNull(T data, BaseServiceException baseServiceException, Object... params) {
        if (Objects.isNull(data)) {
            ThrowUtil.throwMsg(baseServiceException, params);
        }
        return data;
    }


    /**
     * 检查给定字符串是否为空串，为空抛出异常
     *
     * @param data                 被检查对象
     * @param baseServiceException 错误返回码
     * @param params               参数列表
     * @return 被检查后的对象
     */
    public static String isBlank(String data, BaseServiceException baseServiceException, Object... params) {
        if (StringUtils.isBlank(data)) {
            ThrowUtil.throwMsg(baseServiceException, params);
        }
        return data;
    }

    /**
     * 检查给定字符串是否为空白（null、空串或只包含空白符），为空抛出异常
     *
     * @param text                 被检查字符串
     * @param baseServiceException 错误返回码
     * @param params               参数列表
     * @param <T>                  字符串类型
     * @return 非空字符串
     */
    public static <T extends CharSequence> T notBlank(T text, BaseServiceException baseServiceException, Object... params) {
        if (StrUtil.isBlank(text)) {
            ThrowUtil.throwMsg(baseServiceException, params);
        }
        return text;
    }

    /**
     * 断言对象是否不为null ，如果为null抛出异常
     *
     * @param object               被检查对象
     * @param baseServiceException 错误返回码
     * @param params               参数列表
     * @param <T>                  被检查对象泛型类型
     * @return 被检查后的对象
     */
    public static <T> T notNull(T object, BaseServiceException baseServiceException, Object... params) {
        if (Objects.isNull(object)) {
            ThrowUtil.throwMsg(baseServiceException, params);
        }
        return object;
    }

    /**
     * 检查时间是否在时间范围内
     *
     * @param date                 被检查的时间
     * @param startDate            开始时间
     * @param endDate              结束时间
     * @param baseServiceException 错误返回码
     * @param params               参数列表
     * @param <T>                  Date类型
     * @return boolean
     */
    public static <T extends Date> boolean checkDateScope(T date, T startDate, T endDate, BaseServiceException baseServiceException, Object... params) {
        if (Objects.isNull(date) || Objects.isNull(startDate) || Objects.isNull(endDate)) {
            ThrowUtil.throwMsg(baseServiceException, params);
        }
        if (date.before(startDate) || date.after(endDate)) {
            ThrowUtil.throwMsg(baseServiceException, params);
        }
        return true;
    }

    /**
     * 检查时间是否在某个时间之前
     *
     * @param checkDate            检查的时间
     * @param date                 比较的时间
     * @param baseServiceException 错误返回码
     * @param params               参数列表
     * @param <T>                  Date类型
     * @return boolean
     */
    public static <T extends Date> boolean checkDateBefore(T checkDate, T date, BaseServiceException baseServiceException, Object... params) {
        if (Objects.isNull(checkDate) || Objects.isNull(date)) {
            ThrowUtil.throwMsg(baseServiceException, params);
        }
        if (!checkDate.before(date)) {
            ThrowUtil.throwMsg(baseServiceException, params);
        }
        return true;
    }

    /**
     * 检查时间是否在某个时间之后
     *
     * @param checkDate            检查的时间
     * @param date                 比较的时间
     * @param baseServiceException 错误返回码
     * @param params               参数列表
     * @param <T>                  Date类型
     * @return boolean
     */
    public static <T extends Date> boolean checkDateAfter(T checkDate, T date, BaseServiceException baseServiceException, Object... params) {
        if (Objects.isNull(checkDate) || Objects.isNull(date)) {
            ThrowUtil.throwMsg(baseServiceException, params);
        }
        if (!checkDate.after(date)) {
            ThrowUtil.throwMsg(baseServiceException, params);
        }
        return true;
    }

    /**
     * 断言给定集合非空
     *
     * @param collection           被检查的集合
     * @param baseServiceException 错误返回码
     * @param params               参数列表
     * @param <E>                  集合元素类型
     * @param <T>                  集合类型
     * @return 非空集合
     */
    public static <E, T extends Iterable<E>> T notEmpty(T collection, BaseServiceException baseServiceException, Object... params) {
        if (IterUtil.isEmpty(collection)) {
            ThrowUtil.throwMsg(baseServiceException, params);
        }
        return collection;
    }

    /**
     * 断言给定Map非空
     *
     * @param map                  被检查的Map
     * @param baseServiceException 错误返回码
     * @param params               参数列表
     * @param <K>                  Key类型
     * @param <V>                  Value类型
     * @param <T>                  Map类型
     * @return 被检查的Map
     */
    public static <K, V, T extends Map<K, V>> T notEmpty(T map, BaseServiceException baseServiceException, Object... params) {
        if (MapUtil.isEmpty(map)) {
            ThrowUtil.throwMsg(baseServiceException, params);
        }
        return map;
    }

    /**
     * 断言给定数组是否不包含 null元素，如果数组为空或 null将被认为不包含
     *
     * @param array                被检查的数组
     * @param baseServiceException 错误返回码
     * @param params               参数列表
     * @param <T>                  数组元素类型
     * @return 被检查的数组
     */
    public static <T> T[] noNullElements(T[] array, BaseServiceException baseServiceException, Object... params) {
        if (ArrayUtil.hasNull(array)) {
            ThrowUtil.throwMsg(baseServiceException, params);
        }
        return array;
    }
}
